﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using ProgNetComponentsDx.Options;
using ProgNetComponentsDx.Data;
using ProgNetComponents.Data;
using ProgNetComponentsDx.Layout;
using ProgNetComponentsDx.Shortcut;
using System.Drawing.Imaging;

namespace ProgNetComponentsDx.Forms
{
    public partial class BaseInitForm : XtraForm, ICustomTypeDescriptor
    {
        public BaseInitForm()
        {
            InitializeComponent();
            this.BackgroundImageLayout = ImageLayout.Stretch;
            Delay = 250;
            ShouldInitBrowsers = true;
            ShouldInitLanguages = true;
            ShouldInitLayouts = true;
            ShouldInitOptions = true;
            ShouldInitSelectData = true;
            ShouldInitShortcuts = true;
            BackgrounImageTransparentPixel = new Point(1, 1);
            TransparencyTolerance = 0;
            ShapeFromSplashImage = true;
            DoubleBuffered = true;
        }

        #region Properties
        [Category(ProgNetComponents.Constants.Categories.ProgNetSettings)]
        public int Delay
        {
            get;
            set;
        }
        [Category(ProgNetComponents.Constants.Categories.ProgNetSettings)]
        public int FadeInTime
        {
            get;
            set;
        }
        [Category(ProgNetComponents.Constants.Categories.ProgNetSettings)]
        public int FadeOutTime
        {
            get;
            set;
        }
        [Category(ProgNetComponents.Constants.Categories.ProgNetSettings)]
        public bool ShouldInitBrowsers
        {
            get;
            set;
        }
        [Category(ProgNetComponents.Constants.Categories.ProgNetSettings)]
        public bool ShouldInitOptions
        {
            get;
            set;
        }
        [Category(ProgNetComponents.Constants.Categories.ProgNetSettings)]
        public bool ShouldInitSelectData
        {
            get;
            set;
        }
        [Category(ProgNetComponents.Constants.Categories.ProgNetSettings)]
        public bool ShouldInitLanguages
        {
            get;
            set;
        }
        [Category(ProgNetComponents.Constants.Categories.ProgNetSettings)]
        public bool ShouldInitLayouts
        {
            get;
            set;
        }
        [Category(ProgNetComponents.Constants.Categories.ProgNetSettings)]
        public bool ShouldInitShortcuts
        {
            get;
            set;
        }
        [Category(ProgNetComponents.Constants.Categories.ProgNetSettings)]
        public bool ShouldPostInit
        {
            get;
            set;
        }


        [Category(ProgNetComponents.Constants.Categories.ProgNetAppearance)]
        public Point BackgrounImageTransparentPixel
        {
            get;
            set;
        }
        [Category(ProgNetComponents.Constants.Categories.ProgNetAppearance)]
        public Image SplashImage
        {
            get { return BackgroundImage; }
            set { BackgroundImage = value; }
        }

        [Category(ProgNetComponents.Constants.Categories.ProgNetAppearance)]
        public bool ShapeFromSplashImage
        {
            get;
            set;
        }
        [Category(ProgNetComponents.Constants.Categories.ProgNetAppearance)]
        public int TransparencyTolerance
        {
            get;
            set;
        }

        [Browsable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override Image BackgroundImage
        {
            get
            {
                return base.BackgroundImage;
            }
            set
            {
                base.BackgroundImage = value;
            }
        }
        [Browsable(false),
        DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override ImageLayout BackgroundImageLayout
        {
            get
            {
                return base.BackgroundImageLayout;
            }
            set
            {
                base.BackgroundImageLayout = value;
            }
        }
        #endregion

        private void InitForm()
        {
            if (SplashImage != null)
            {
                Bitmap bmp = SplashImage.ResizeImage(this.Width, this.Height);
                this.DoubleBuffered = true;
                this.BackgroundImage = bmp;
                this.BackgroundImageLayout = ImageLayout.Stretch;
                if (ShapeFromSplashImage)
                {
                    this.Region = bmp.GetRegionFast(bmp.GetPixel(BackgrounImageTransparentPixel), TransparencyTolerance);
                }
            }
        }

        public void InitAll()
        {
            backgroundWorker1.RunWorkerAsync();
        }

        protected void SetProgressText(string text)
        {
            if (lblText.InvokeRequired)
                lblText.Invoke(new Action<string>(SetProgressText), text);
            else
                lblText.Text = text;
        }

        protected void SetLblVisibility(LabelControl lbl, bool visible)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action<LabelControl, bool>(SetLblVisibility), lbl, visible);
                return;
            }
            lbl.Visible = visible;
        }

        #region Init functions
        protected virtual void PreInit()
        {
            SetProgressText("Inicjowanie aplikacji.");
        }
        protected virtual void InitOptions()
        {
            SetProgressText("Inicjowanie opcji.");

            OptionCache.Grabber = CreateOptionGrabber();
            if (OptionCache.Grabber != null)
            {
                OptionCache.RegisterGroups(this.optionContainer1.Items, this.GetType(this.GetType().FullName + "OptionNames"));
                OptionCache.GetOptions();
            }
        }
        protected virtual void InitSelectData()
        {
            SetProgressText("Inicjowanie zapytań.");
            ProgNetComponentsDx.Data.SelectDataCache.ManagerCreator = CreateDataManagerCreator();
            if (ProgNetComponentsDx.Data.SelectDataCache.ManagerCreator != null)
            {
                ProgNetComponentsDx.Data.SelectDataCache.RegisterGroups(selectDataContainer1.Items, this.GetType(this.GetType().FullName + "SelectDataNames"));
            }
        }
        protected virtual void InitBrowsers()
        {
            SetProgressText("Inicjowanie źrudeł danych.");
            ProgNetComponentsDx.Browsers.BrowserCache.DataManager = CreateDataManagerForBrowsers();
            if (ProgNetComponentsDx.Browsers.BrowserCache.DataManager != null)
            {
                ProgNetComponentsDx.Browsers.BrowserCache.RegisterGroups(this.browserContainer1.Items, this.GetType(this.GetType().FullName + "BrowserNames"));
                ProgNetComponentsDx.Browsers.BrowserCache.GetStaticData += new ProgNetComponentsDx.Browsers.GetStaticBrowserDataDelegate(BrowserCache_GetStaticData);
            }
        }
        protected virtual void InitShorcuts()
        {
            SetProgressText("Inicjowanie skrutów.");
            ShortcutCache.Grabber = CreateShotrcutsGrabber();
            if (ShortcutCache.Grabber != null)
            {
                ShortcutCache.RegisterGroups(this.shortcutContainer1.Items, this.GetType(this.GetType().FullName + "ShortcutNames"));
                ShortcutCache.GetShortcuts();
            }
        }
        protected virtual void InitLangouage()
        {
            SetProgressText("Inicjowanie języków.");
        }
        protected virtual void InitLayouts()
        {
            SetProgressText("Inicjowanie wyglądu");
            LayoutGrabber.Instance = CreateLayoutGrabber();
        }
        protected virtual void PostInit()
        {
            SetProgressText("Finalizowanie.");
        }
        protected virtual DataManager CreateDataManagerForBrowsers()
        {
            return null;
        }
        protected virtual OptionGrabber CreateOptionGrabber()
        {
            return null;
        }
        protected virtual SelectDataManagerCreator CreateDataManagerCreator()
        {
            return null;
        }
        protected virtual LayoutGrabber CreateLayoutGrabber()
        {
            return null;
        }

        protected virtual ShortcutGrabber CreateShotrcutsGrabber()
        {
            return null;
        }
        #endregion

        #region Browsers Static Data
        protected virtual DataTable BrowserCache_GetStaticData(object browserId)
        {
            return null;
        }
        #endregion

        protected void SetDelay()
        {
            if (Delay > 0)
                System.Threading.Thread.Sleep(Delay);
        }

        protected virtual void SetAstions(List<Action> actions)
        {
            actions.Add(PreInit);
            if (ShouldInitOptions)
                actions.Add(InitOptions);
            if (ShouldInitLanguages)
                actions.Add(InitLangouage);
            if (ShouldInitSelectData)
                actions.Add(InitSelectData);
            if (ShouldInitBrowsers)
                actions.Add(InitBrowsers);
            if (ShouldInitLayouts)
                actions.Add(InitLayouts);
            if (ShouldInitShortcuts)
                actions.Add(InitShorcuts);
            if (ShouldPostInit)
                actions.Add(PostInit);
        }
        
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            
            if (!this.IsDesignMode())
            {
                InitAll();
            }
        }
       
        public new DialogResult ShowDialog()
        {
            InitForm();
            User32.FadeIn(this.Handle, FadeInTime);
            return  base.ShowDialog();
        }
       
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            List<Action> actions = new List<Action>();
            SetAstions(actions);
            foreach (Action a in actions)
            {
                a.Invoke();
                SetDelay();
            }
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            User32.FadeOut(this.Handle, FadeOutTime);
            this.Close();
        }

        #region ICustomTypeDescriptor Members
        private bool noCustomTypeDesc = true;
        AttributeCollection ICustomTypeDescriptor.GetAttributes()
        {
            return TypeDescriptor.GetAttributes(this, noCustomTypeDesc);
        }

        string ICustomTypeDescriptor.GetClassName()
        {
            return TypeDescriptor.GetClassName(this, noCustomTypeDesc);
        }

        string ICustomTypeDescriptor.GetComponentName()
        {
            return TypeDescriptor.GetComponentName(this, noCustomTypeDesc);
        }

        TypeConverter ICustomTypeDescriptor.GetConverter()
        {
            return TypeDescriptor.GetConverter(this, noCustomTypeDesc);
        }

        EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
        {
            return TypeDescriptor.GetDefaultEvent(this, noCustomTypeDesc);
        }

        PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
        {
            return TypeDescriptor.GetDefaultProperty(this, noCustomTypeDesc);
        }

        object ICustomTypeDescriptor.GetEditor(Type editorBaseType)
        {
            return TypeDescriptor.GetEditor(this, editorBaseType, noCustomTypeDesc);
        }

        EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
        {
            return TypeDescriptor.GetEvents(this, attributes, noCustomTypeDesc);
        }

        EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
        {
            return TypeDescriptor.GetEvents(this, noCustomTypeDesc);
        }

        PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
        {
            return (this as ICustomTypeDescriptor).GetProperties();
        }

        private PropertyDescriptorCollection props = null;
        PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
        {
            if(props !=null )
                return props;

            props =  TypeDescriptor.GetProperties(this, noCustomTypeDesc);
            List<PropertyDescriptor> add = new List<PropertyDescriptor>();
            foreach (PropertyDescriptor d in props)
            {
                if (d.ComponentType == this.GetType() ||
                    !d.IsBrowsable ||
                    d.Name == "Name" ||
                    d.Name == "Size" ||
                    d.Name == "ClientSize" ||
                    d.Name == "Size" ||
                    d.Name == "TopMost" ||
					d.Name == "Text" ||
                    d.Name == "BackColor" ||
                    d.Name == "BackgroundImage" || 
                    d.Name == "BackgroundImageLayout")
                {
                    add.Add(d);
                }
            }
            props = new PropertyDescriptorCollection(add.ToArray());
            return props;
        }

        object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
        {
            return this;
        }

        #endregion

    }
}
